package cn.bandeqing.order.rpc.impl;

import cn.bandeqing.base.aliyun.SmsUtil;
import cn.bandeqing.base.domain.AdminUserStore;
import cn.bandeqing.base.domain.CurrentAdminUser;
import cn.bandeqing.base.resp.Resp;
import cn.bandeqing.base.resp.Table;
import cn.bandeqing.base.tencentcloud.SendSms;
import cn.bandeqing.base.tencentcloud.TemplateId;
import cn.bandeqing.config.service.IConfigService;
import cn.bandeqing.douyin.util.DouYinUtil;
import cn.bandeqing.finance.resp.LabelValue;
import cn.bandeqing.frame.exception.CodeException;
import cn.bandeqing.order.entity.Order;
import cn.bandeqing.order.entity.OrderStatus;
import cn.bandeqing.order.req.*;
import cn.bandeqing.order.resp.*;
import cn.bandeqing.order.rpc.IOrderRpc;
import cn.bandeqing.order.service.IOrderService;
import cn.bandeqing.orderDiscounts.entity.DiscountsType;
import cn.bandeqing.orderDiscounts.entity.OrderDiscounts;
import cn.bandeqing.orderDiscounts.service.IOrderDiscountsService;
import cn.bandeqing.payRecord.entity.DouyinCodeStatus;
import cn.bandeqing.payRecord.entity.PayRecord;
import cn.bandeqing.payRecord.entity.PaySource;
import cn.bandeqing.payRecord.entity.PayType;
import cn.bandeqing.payRecord.service.IPayRecordService;
import cn.bandeqing.product.entity.Product;
import cn.bandeqing.product.service.IProductService;
import cn.bandeqing.productInventory.entity.ProductInventory;
import cn.bandeqing.productInventory.service.IProductInventoryService;
import cn.bandeqing.productInventoryRecord.entity.ChangeType;
import cn.bandeqing.productInventoryRecord.entity.ProductInventoryRecord;
import cn.bandeqing.productInventoryRecord.service.IProductInventoryRecordService;
import cn.bandeqing.productSpecification.entity.ProductSpecification;
import cn.bandeqing.productSpecification.service.IProductSpecificationService;
import cn.bandeqing.shortMessage.entity.ShortMessage;
import cn.bandeqing.shortMessage.service.IShortMessageService;
import cn.bandeqing.store.entity.Store;
import cn.bandeqing.store.service.IStoreService;
import cn.bandeqing.stp.StpAdminUtil;
import cn.binarywang.wx.miniapp.api.WxMaCloudService;
import cn.binarywang.wx.miniapp.api.WxMaService;
import cn.binarywang.wx.miniapp.bean.cloud.WxCloudSendSmsV2Result;
import cn.binarywang.wx.miniapp.bean.cloud.request.WxCloudSendSmsV2Request;
import cn.binarywang.wx.miniapp.bean.urllink.GenerateUrlLinkRequest;
import com.mybatisflex.core.paginate.Page;
import com.mybatisflex.core.query.QueryWrapper;
import io.github.linpeilie.Converter;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.common.error.WxErrorException;
import org.apache.dubbo.config.annotation.DubboService;
import org.dromara.hutool.core.date.DatePattern;
import org.dromara.hutool.core.date.DateUtil;
import org.dromara.hutool.core.lang.Assert;
import org.dromara.hutool.core.text.StrUtil;
import org.dromara.hutool.core.util.ObjUtil;
import org.dromara.hutool.json.JSONArray;
import org.dromara.hutool.json.JSONObject;
import org.springframework.transaction.annotation.Transactional;

import java.sql.Timestamp;
import java.util.List;

import static cn.bandeqing.order.entity.table.OrderTableDef.ORDER;
import static cn.bandeqing.orderDiscounts.entity.table.OrderDiscountsTableDef.ORDER_DISCOUNTS;
import static cn.bandeqing.product.entity.table.ProductTableDef.PRODUCT;
import static cn.bandeqing.productInventory.entity.table.ProductInventoryTableDef.PRODUCT_INVENTORY;
import static cn.bandeqing.productInventoryRecord.entity.table.ProductInventoryRecordTableDef.PRODUCT_INVENTORY_RECORD;
import static cn.bandeqing.productSpecification.entity.table.ProductSpecificationTableDef.PRODUCT_SPECIFICATION;
import static cn.bandeqing.store.entity.table.StoreTableDef.STORE;

@Slf4j
@DubboService
public class OrderRpcImpl implements IOrderRpc {

    @Resource
    private IOrderService orderService;
    @Resource
    private IOrderDiscountsService orderDiscountsService;
    @Resource
    private IProductInventoryRecordService productInventoryRecordService;
    @Resource
    private IProductInventoryService productInventoryService;
    @Resource
    private IProductService productService;
    @Resource
    private IProductSpecificationService productSpecificationService;
    @Resource
    private IPayRecordService payRecordService;
    @Resource
    private IStoreService storeService;
    @Resource
    private WxMaService wxMaService;
    @Resource
    private IShortMessageService shortMessageService;
    @Resource
    private IConfigService configService;
    @Resource
    private Converter converter;

    @Override
    public Resp<Table<OrderTable>> table(OrderTableReq req) {
        QueryWrapper qw = QueryWrapper.create()
                .where(ORDER.ORDER_ID.eq(req.getOrderId()))
                .where(ORDER.SERVICE_TIME.ge(req.getServiceTimeStart()))
                .where(ORDER.SERVICE_TIME.le(req.getServiceTimeEnd()))
                .where(ORDER.CREATE_TIME.ge(req.getCreateTimeStart()))
                .where(ORDER.CREATE_TIME.le(req.getCreateTimeEnd()))
                .where(ORDER.CUSTOMER_NAME.eq(req.getCustomerName()))
                .where(ORDER.CUSTOMER_PHONE.eq(req.getCustomerPhone()))
                .where(ORDER.START_ADDRESS.eq(req.getStartAddress()))
                .where(ORDER.NEW_ADDRESS.eq(req.getNewAddress()))
                .where(ORDER.ORDER_STATUS.eq(req.getOrderStatus()))
                .where(ORDER.STORE_ID.eq(req.getStoreId()))
                .orderBy(ORDER.ORDER_ID.desc());

        if (req.getStoreId() == null) {
            CurrentAdminUser current = StpAdminUtil.getCurrent();
            if (current.checkStoreAccount()) {
                // 店铺账号 只能查询店铺下的权限
                qw.where(ORDER.STORE_ID.in(current.getStores().stream().map(AdminUserStore::getStoreId).toList()));
            }
        }

        Page<OrderTable> page = orderService.pageAs(Page.of(req.getCurrent(), req.getPageSize()), qw, OrderTable.class);
        return Resp.success(Table.of(page.getRecords(), page.getTotalRow()));
    }

    @Override
    public void saveOrUpdate(OrderSaveOrUpdateReq req) {
        Order order = converter.convert(req, Order.class);

        if (StrUtil.isNotBlank(req.getServiceTimeStr())) {
            order.setServiceTime(new Timestamp(DateUtil.parse(req.getServiceTimeStr(), DatePattern.NORM_DATETIME_FORMAT).getTime()));
        }

        if (order.getOrderId() == null) {
            order.setOrderId(System.currentTimeMillis());
            order.setOrderStatus(OrderStatus.wait_deposit);
            Assert.isTrue(orderService.save(order), () -> new CodeException("orderService.save(order)"));
        } else {

            Order dbOrder = orderService.getOne(QueryWrapper.create()
                    .select(ORDER.WRITE_OFF_TIME)
                    .where(ORDER.ORDER_ID.eq(req.getOrderId())));

//            Assert.isTrue(dbOrder == null || dbOrder.getWriteOffTime() == null, () -> new CodeException("订单已经核销，无法修改"));

            Assert.isNull(dbOrder, () -> new CodeException("订单已经核销，无法修改"));
//            Assert.isNull(dbOrder.getWriteOffTime(), () -> new CodeException("订单已经核销，无法修改"));

            Assert.isTrue(orderService.updateById(order), () -> new CodeException("orderService.updateById(order)"));
        }
    }

    @Override
    public Resp<OrderDetailResp> detail(OrderDetailReq req) {
        OrderDetailResp detailResp = orderService.getOneAs(QueryWrapper.create()
                .where(ORDER.ORDER_ID.eq(req.getOrderId())), OrderDetailResp.class);

        List<OrderDetailResp.ProductDetail> productDetails = productInventoryRecordService.listAs(QueryWrapper.create()
                .where(PRODUCT_INVENTORY_RECORD.ORDER_ID.eq(req.getOrderId()))
                .where(PRODUCT_INVENTORY_RECORD.CHANGE_TYPE.in(ChangeType.order_save)), OrderDetailResp.ProductDetail.class);

        detailResp.setProductDetails(productDetails);
        StringBuilder productDetailsStr = new StringBuilder();

        if (productDetails.size() == 1) {
            OrderDetailResp.ProductDetail pd = productDetails.getFirst();
            productDetailsStr.append(StrUtil.format("{}({})*{}({})={}", pd.getProductName(),
                    pd.getProductSpecification(), pd.getChangeInventory(), pd.getProductPrice(), pd.getProductTotalPrice()));
        } else {
            for (int i = 0; i < productDetails.size(); i++) {
                OrderDetailResp.ProductDetail pd = productDetails.get(i);
                if (i == productDetails.size() - 1) {
                    productDetailsStr.append(StrUtil.format("{}({})*{}({})={}", pd.getProductName(),
                            pd.getProductSpecification(), pd.getChangeInventory(), pd.getProductPrice(), pd.getProductTotalPrice()));
                } else {
                    productDetailsStr.append(StrUtil.format("{}({})*{}({})={}+", pd.getProductName(),
                            pd.getProductSpecification(), pd.getChangeInventory(), pd.getProductPrice(), pd.getProductTotalPrice()));
                }
            }
        }

        detailResp.setProductDetailsStr(productDetailsStr.toString());
        return Resp.success(detailResp);
    }

    @Override
    @Transactional
    public Resp<Void> modifyStatus(OrderModifyStatusReq req) {
        Order order = orderService.getById(req.getOrderId());
        Order updateOrder = converter.convert(req, Order.class);

        if (ObjUtil.isNotNull(req.getPayMoney()) && ObjUtil.isNotNull(req.getPayType()) && ObjUtil.isNotNull(req.getPaySource())) {
            PayRecord pr = converter.convert(req, PayRecord.class);

            if (req.getPayType() == 0) {
                Double payDeposit = ObjUtil.defaultIfNull(order.getPayDeposit(), 0.0) + req.getPayMoney();
                updateOrder.setPayDeposit(payDeposit);

                pr.setPayBeforeDeposit(order.getPayDeposit());
                pr.setPayAfterDeposit(payDeposit);

                pr.setPayBeforeFinalPayment(order.getPayFinalPayment());
                pr.setPayAfterFinalPayment(order.getPayFinalPayment());

            } else if (req.getPayType() == 1) {
                Double payFinalPayment = ObjUtil.defaultIfNull(order.getPayFinalPayment(), 0.0) + req.getPayMoney();
                updateOrder.setPayFinalPayment(payFinalPayment);

                pr.setPayBeforeFinalPayment(order.getPayFinalPayment());
                pr.setPayAfterFinalPayment(payFinalPayment);

                pr.setPayBeforeDeposit(order.getPayDeposit());
                pr.setPayAfterDeposit(order.getPayDeposit());
            }


            pr.setPayAfterTotalPrice(order.getTotalPrice());
            pr.setPayBeforeTotalPrice(order.getTotalPrice());

            Assert.isTrue(payRecordService.save(pr), CodeException::new);

        } else {
            // 只修改状态
            Assert.isFalse(order.getOrderStatus().getValue().equals(req.getOrderStatus()),
                    () -> new CodeException("订单状态一致，无需修改，操作订单支付需要一并选中支付类型和支付渠道。"));
        }

        if (OrderStatus.wait_deposit.equals(updateOrder.getOrderStatus())) {
            // 订单修改为待确认 发送短信


//            GenerateUrlLinkRequest request = new GenerateUrlLinkRequest();
//            request.setPath("commPages/transferpath/transferpath");
//            request.setQuery("operateType=0");
//            request.setExpireType(1);
//            request.setExpireInterval(365);
//            try {
            // https://wxaurl.cn/GsvO89l5Pvp 2024-04-07 11:30:09 365天有效期
//                String url = wxMaService.getLinkService().generateUrlLink(request);
//                log.info("url = {}", url);

            ShortMessage shortMessage = ShortMessage.builder()
                    .smPhone(order.getCustomerPhone())
                    .smContent(TemplateId.T_2119888.getTemplateId())
                    .smProviderType(0)
                    .smArrive(false)
                    .build();
            Assert.isTrue(shortMessageService.save(shortMessage), () -> new CodeException("短信记录插入失败"));

            Double shouldDeposit = order.getShouldDeposit();
            if (shouldDeposit == null) {
                shouldDeposit = Double.valueOf(configService.keyInt("default_deposit", 100));
            }
//                SmsUtil.sendOrderWaitPayDeposit(order.getOrderId(), order.getCustomerName(), order.getCustomerPhone(), url.substring(18), shouldDeposit);

//                String[] templateParamSet = {order.getCustomerName(), order.getOrderId().toString().substring(7), shouldDeposit.toString()};
            String[] templateParamSet = {order.getCustomerName(), "", shouldDeposit.toString()};
            String[] phoneNumberSet = {order.getCustomerPhone()};

            SendSms.send("斑得清小程序", TemplateId.T_2119888.getTemplateId(), templateParamSet, phoneNumberSet);

//                WxCloudSendSmsV2Result result = wxMaService.getCloudService().sendSmsV2(WxCloudSendSmsV2Request.builder()
//                        .build());

//            } catch (WxErrorException e) {
//                log.error("", e);
//            }
        }

        Assert.isTrue(orderService.updateById(updateOrder), CodeException::new);
        return Resp.success();
    }

    @Override
    public Resp<Table<OrderDiscountsTable>> discountsTable(OrderDiscountsTableReq req) {
        QueryWrapper qw = QueryWrapper.create()
                .where(ORDER_DISCOUNTS.ORDER_ID.eq(req.getOrderId()))
//                .where(ORDER_DISCOUNTS.DISCOUNTS_TYPE.eq(DiscountsType.other_price, req.getOtherPrice()))
                .orderBy(ORDER_DISCOUNTS.DISCOUNTS_ID.desc());

        if (req.getOtherPrice()) {
            qw.where(ORDER_DISCOUNTS.DISCOUNTS_TYPE.eq(DiscountsType.other_price));
        } else {
            qw.where(ORDER_DISCOUNTS.DISCOUNTS_TYPE.ne(DiscountsType.other_price));
        }

        Page<OrderDiscountsTable> page = orderDiscountsService.pageAs(Page.of(req.getCurrent(), req.getPageSize()), qw, OrderDiscountsTable.class);
        return Resp.success(Table.of(page.getRecords(), page.getTotalRow()));
    }

    @Override
    @Transactional
    public Resp<OrderPriceDetails> discountsSave(OrderDiscountsSaveReq req) {

        Order order = orderService.getById(req.getOrderId());
        Double before = order.getTotalPrice();

        Double discountsPrice;
        Double totalPrice;
        Double otherPrice;

        if (DiscountsType.other_price.getValue().equals(req.getDiscountsType())) {
            // 其他费用
            discountsPrice = ObjUtil.defaultIfNull(order.getDiscountsPrice(), 0.0);
            otherPrice = ObjUtil.defaultIfNull(order.getOtherPrice(), 0.0) + req.getDiscountsMoney();
            totalPrice = before + req.getDiscountsMoney();
        } else {
            // 优惠金额
            discountsPrice = ObjUtil.defaultIfNull(order.getDiscountsPrice(), 0.0) + req.getDiscountsMoney();
            otherPrice = ObjUtil.defaultIfNull(order.getOtherPrice(), 0.0);
            totalPrice = before - req.getDiscountsMoney();
        }

        boolean b = orderService.updateById(Order.builder()
                .orderId(order.getOrderId())
                .otherPrice(otherPrice)
                .discountsPrice(discountsPrice)
                .totalPrice(totalPrice)
                .build());
        Assert.isTrue(b, CodeException::new);

        OrderDiscounts od = converter.convert(req, OrderDiscounts.class);
        od.setBeforeTotalPrice(before);
        od.setAfterTotalPrice(totalPrice);
        boolean save = orderDiscountsService.save(od);
        Assert.isTrue(save, CodeException::new);

        return Resp.success(OrderPriceDetails.builder()
                .discountsPrice(discountsPrice)
                .totalPrice(totalPrice)
                .otherPrice(otherPrice)
                .build());

    }

    @Override
    public Resp<Table<OrderProductTable>> productTable(OrderProductTableReq req) {
        QueryWrapper qw = QueryWrapper.create()
                .where(PRODUCT_INVENTORY_RECORD.ORDER_ID.eq(req.getOrderId()))
                .where(PRODUCT_INVENTORY_RECORD.CHANGE_TYPE.in(ChangeType.order_save))
                .orderBy(PRODUCT_INVENTORY_RECORD.PRODUCT_INVENTORY_RECORD_ID.desc());

        Page<OrderProductTable> page = productInventoryRecordService.pageAs(Page.of(req.getCurrent(), req.getPageSize()), qw, OrderProductTable.class);
        return Resp.success(Table.of(page.getRecords(), page.getTotalRow()));
    }

    @Override
    @Transactional
    public Resp<OrderPriceDetails> productSave(OrderProductSaveReq req) {
        ProductInventoryRecord pir = converter.convert(req, ProductInventoryRecord.class);

        ProductInventory dbPi = productInventoryService.getOne(QueryWrapper.create()
                .where(PRODUCT_INVENTORY.PRODUCT_ID.eq(req.getProductId()))
                .where(PRODUCT_INVENTORY.STORE_ID.eq(req.getStoreId()))
                .where(PRODUCT_INVENTORY.PRODUCT_SPECIFICATION_ID.eq(req.getProductSpecificationId())));

        Assert.notNull(dbPi, () -> new CodeException("店铺没有对应产品库存"));

        Integer before = dbPi.getProductInventory();
        Integer after = before - req.getChangeInventory();
        pir.setBeforeInventory(before);
        pir.setAfterInventory(after);
        pir.setInventoryId(dbPi.getInventoryId());
        pir.setRemark("订单套餐产品服务内容");
        pir.setChangeType(ChangeType.order_save);
//        pir.setChangeInventory(-req.getChangeInventory());

        ProductSpecification ps = productSpecificationService.getOne(QueryWrapper.create()
                .where(PRODUCT_SPECIFICATION.PRODUCT_SPECIFICATION_ID.eq(req.getProductSpecificationId())));

        pir.setProductPrice(ps.getProductPrice());
        pir.setProductTotalPrice(ps.getProductPrice() * pir.getChangeInventory());

        boolean b = productInventoryService.updateById(ProductInventory.builder()
                .inventoryId(dbPi.getInventoryId())
                .productInventory(after)
                .build());
        Assert.isTrue(b, CodeException::new);

        boolean save = productInventoryRecordService.save(pir);
        Assert.isTrue(save, CodeException::new);

        Order order = orderService.getById(req.getOrderId());
        Double productTotalPrice = ObjUtil.defaultIfNull(order.getProductTotalPrice(), 0.0) + pir.getProductTotalPrice();

        // 这一次新增的金额
        Double totalPrice = ObjUtil.defaultIfNull(order.getTotalPrice(), 0.0) + pir.getProductTotalPrice();

        Order o = Order.builder()
                .orderId(order.getOrderId())
                .productTotalPrice(productTotalPrice)
                .totalPrice(totalPrice)
                .build();

        if (order.getProductId() == null) {
            // 设置主要显示套餐
            Product p = productService.getById(req.getProductId());
            if (p.getProductMain()) {
                o.setProductId(p.getProductId());
                o.setProductName(p.getProductName());
            }
        }

        boolean b1 = orderService.updateById(o);
        Assert.isTrue(b1, CodeException::new);

        return Resp.success(OrderPriceDetails.builder()
                .productTotalPrice(productTotalPrice)
                .totalPrice(totalPrice)
                .productName(o.getProductName())
                .build());
    }

    @Override
    public Resp<List<LabelValue>> productSelect(OrderProductSelectReq req) {
//        if (ObjUtil.isNotNull(req.getProductId())) {
//            // 查询对应店铺规格
//            List<LabelValue> labelValues = productInventoryService.listAs(QueryWrapper.create()
//                    .select(PRODUCT_INVENTORY.PRODUCT_SPECIFICATION_ID.as(LabelValue::getValue),
//                            PRODUCT_INVENTORY.PRODUCT_SPECIFICATION.as(LabelValue::getLabel))
//                    .where(PRODUCT_INVENTORY.STORE_ID.eq(req.getStoreId()))
//                    .where(PRODUCT_INVENTORY.PRODUCT_ID.eq(req.getProductId())), LabelValue.class);
//            return Resp.success(labelValues);
//        }

        // 查询对应店铺库存
        List<LabelValue> labelValues = productService.listAs(QueryWrapper.create()
                .select(PRODUCT.PRODUCT_ID.as(LabelValue::getValue),
                        PRODUCT.PRODUCT_NAME.as(LabelValue::getLabel))
                .where(PRODUCT.PRODUCT_NAME.like(req.getKeyWords()))
                .limit(50), LabelValue.class);
        return Resp.success(labelValues);
    }

    @Override
    public Resp<List<LabelValue>> productSpecificationsSelect(OrderProductSpecificationsSelectReq req) {
        List<LabelValue> labelValues = productSpecificationService.listAs(QueryWrapper.create()
                .select(PRODUCT_SPECIFICATION.PRODUCT_SPECIFICATION_ID.as(LabelValue::getValue),
                        PRODUCT_SPECIFICATION.PRODUCT_SPECIFICATION_.as(LabelValue::getLabel))
                .where(PRODUCT_SPECIFICATION.PRODUCT_ID.eq(req.getProductId())), LabelValue.class);

//        labelValues.forEach(lv -> {
//            lv.setLabel(lv.getProductSpecification());
//            lv.setValue(lv.getInventoryId());
//        });

        return Resp.success(labelValues);
    }

    @Override
    @Transactional
    public Resp<OrderPriceDetails> productRemove(OrderProductRemoveReq req) {
        ProductInventoryRecord pir = productInventoryRecordService.getById(req.getProductInventoryRecordId());
        productInventoryRecordService.removeById(req.getProductInventoryRecordId());

        Integer changeInventory = pir.getChangeInventory();
        Long inventoryId = pir.getInventoryId();
        ProductInventory pi = productInventoryService.getById(inventoryId);

        Integer afterInventory = pi.getProductInventory() + changeInventory;

        ProductInventory updatePi = ProductInventory.builder()
                .inventoryId(pi.getInventoryId())
                .productInventory(afterInventory)
                .build();
        boolean b = productInventoryService.updateById(updatePi);
        Assert.isTrue(b, CodeException::new);

        ProductInventoryRecord savePir = ProductInventoryRecord.builder()
                .beforeInventory(pi.getProductInventory())
                .changeInventory(changeInventory)
                .afterInventory(afterInventory)
                .productId(pir.getProductId())
                .productSpecificationId(pir.getProductSpecificationId())
                .productSpecification(pir.getProductSpecification())
                .productName(pir.getProductName())
                .inventoryId(pir.getInventoryId())
                .storeId(pir.getStoreId())
                .storeName(pir.getStoreName())
                .changeType(ChangeType.order_remove)
                .remark("订单删除退还库存")
                .productPrice(pir.getProductPrice())
                .productTotalPrice(pir.getProductTotalPrice())
                .orderId(pir.getOrderId())
                .build();
        boolean save = productInventoryRecordService.save(savePir);
        Assert.isTrue(save, CodeException::new);

        Long orderId = pir.getOrderId();
        Order order = orderService.getById(orderId);

        Double totalPrice = order.getTotalPrice() - pir.getProductTotalPrice();
        Double productTotalPrice = order.getProductTotalPrice() - pir.getProductTotalPrice();

        Order updateOrder = Order.builder()
                .orderId(orderId)
                .productTotalPrice(productTotalPrice)
                .totalPrice(totalPrice)
                .build();
        boolean b1 = orderService.updateById(updateOrder);
        Assert.isTrue(b1, CodeException::new);

        return Resp.success(OrderPriceDetails.builder()
                .totalPrice(totalPrice)
                .productTotalPrice(productTotalPrice)
                .build());
    }

    @Override
    @Transactional
    public Resp<Void> douyinVerify(DouyinVerifyReq req) {
        Store store = storeService.getOne(STORE.DOUYIN_POI_ID.eq(req.getDouyinPoiId()));
        JSONObject prepare = DouYinUtil.prepare(req.getCode());
        JSONObject data = prepare.getJSONObject("data");
        JSONArray certificates = data.getJSONArray("certificates");
        JSONObject certificate = certificates.getJSONObject(0);
        JSONObject amount = certificate.getJSONObject("amount");
        // 划线价 分
        Integer listMarketAmount = amount.getInt("list_market_amount");
        // 券原始金额 分
        Integer originalAmount = amount.getInt("original_amount");

        // 套餐的价格
        Double productTotalPrice = listMarketAmount / 100.0;
        // 支付的定金 即套餐总价
        Double payDeposit = originalAmount / 100.0;
        Double discountsPrice = productTotalPrice - payDeposit;

        JSONObject sku = certificate.getJSONObject("sku");
        String skuId = sku.getStr("sku_id");
        String title = sku.getStr("title");
        if (title.contains("代金券")) {
            return Resp.error("无订单验券 不可验代金券");
        }

        Product product = productService.getOne(PRODUCT.DOUYIN_PRODUCT_ID.eq(skuId));
        Assert.notNull(product, () -> new CodeException("券码对应产品未在斑得清系统初始化"));
        ProductSpecification ps = productSpecificationService.getOne(PRODUCT_SPECIFICATION.PRODUCT_ID.eq(product.getProductId()));
        Assert.notNull(ps, () -> new CodeException("抖音团购请配置一个基础套餐即可"));
        ProductInventory pi = productInventoryService.getOne(QueryWrapper.create()
                .where(PRODUCT_INVENTORY.PRODUCT_ID.eq(product.getProductId()))
                .where(PRODUCT_INVENTORY.PRODUCT_SPECIFICATION_ID.eq(ps.getProductSpecificationId()))
                .where(PRODUCT_INVENTORY.STORE_ID.eq(store.getStoreId())));
        Assert.notNull(pi, () -> new CodeException("店铺未入库抖音团购产品"));

        String verifyToken = data.getStr("verify_token");
        String encryptedCode = certificate.getStr("encrypted_code");
        String orderId = data.getStr("order_id");

        JSONObject entries = DouYinUtil.certificateVerify(verifyToken, req.getDouyinPoiId(), encryptedCode, orderId);
        JSONObject jsonObject = entries.getJSONObject("data");
        Integer errorCode = jsonObject.getInt("error_code", -1);
        if (errorCode != 0) {
            String description = jsonObject.getStr("description");
            return Resp.error(description);
        }

        Order order = Order.builder()
                .orderId(System.currentTimeMillis())
                .orderStatus(OrderStatus.confirm)
                .customerName(req.getCustomerName())
                .customerPhone(req.getCustomerPhone())
                .productId(product.getProductId())
                .productName(product.getProductName())
                .productTotalPrice(productTotalPrice)
                .discountsPrice(discountsPrice)
                .totalPrice(payDeposit)
                .payDeposit(payDeposit)
                .storeId(store.getStoreId())
                .storeName(store.getStoreName())
                .cityCode(store.getCityCode())
                .cityName(store.getCityName())
                .build();
        Assert.isTrue(orderService.save(order), CodeException::new);

        OrderDiscounts od = OrderDiscounts.builder()
                .orderId(order.getOrderId())
                .beforeTotalPrice(productTotalPrice)
                .discountsMoney(discountsPrice)
                .afterTotalPrice(payDeposit)
                .discountsType(DiscountsType.douyin)
                .discountsRemark("抖音团购" + product.getProductName() + "优惠" + discountsPrice + "元")
                .build();
        Assert.isTrue(orderDiscountsService.save(od), CodeException::new);

        PayRecord pr = PayRecord.builder()
                .orderId(order.getOrderId())
                .payMoney(payDeposit)
                .payType(PayType.prepay)
                .paySource(PaySource.douyin)
                .payRemark(req.getRemark())
                .payBeforeDeposit(0.0)
                .payAfterDeposit(payDeposit)
                .payBeforeFinalPayment(0.0)
                .payAfterFinalPayment(0.0)
                .payBeforeTotalPrice(productTotalPrice)
                .payAfterTotalPrice(payDeposit)
                .douyinCode(req.getCode())
                .douyinCodeStatus(DouyinCodeStatus.pass)
                .build();
        Assert.isTrue(payRecordService.save(pr), CodeException::new);

        Integer before = pi.getProductInventory();
        Integer after = pi.getProductInventory() - 1;
        ProductInventory updatePi = ProductInventory.builder()
                .inventoryId(pi.getInventoryId())
                .productInventory(after)
                .build();
        Assert.isTrue(productInventoryService.updateById(updatePi), CodeException::new);

        ProductInventoryRecord pir = ProductInventoryRecord.builder()
                .inventoryId(pi.getInventoryId())
                .productId(pi.getProductId())
                .productSpecificationId(ps.getProductSpecificationId())
                .productSpecification(ps.getProductSpecification())
                .productId(product.getProductId())
                .productName(product.getProductName())
                .productPrice(productTotalPrice)
                .productTotalPrice(productTotalPrice)
                .storeId(store.getStoreId())
                .storeName(store.getStoreName())
                .beforeInventory(before)
                .changeInventory(1)
                .afterInventory(after)
                .orderId(order.getOrderId())
                .changeType(ChangeType.order_save)
                .remark("抖音验券订单新增")
                .build();
        Assert.isTrue(productInventoryRecordService.save(pir), CodeException::new);

        return Resp.success();
    }

    @Override
    @Transactional
    public Resp<Void> orderDouyinVerify(OrderDouyinVerifyReq req) {
        Order order = orderService.getById(req.getOrderId());
        Assert.notNull(order.getStoreId(), () -> new CodeException("订单未选择店铺"));

        JSONObject prepare = DouYinUtil.prepare(req.getDouyinCode());
        JSONObject data = prepare.getJSONObject("data");
        JSONArray certificates = data.getJSONArray("certificates");
        JSONObject certificate = certificates.getJSONObject(0);
        JSONObject amount = certificate.getJSONObject("amount");
        // 划线价 分
        Integer listMarketAmount = amount.getInt("list_market_amount");
        // 券原始金额 分
        Integer originalAmount = amount.getInt("original_amount");

        // 套餐的价格
        Double productTotalPrice = listMarketAmount / 100.0;
        // 支付的金额 即套餐总价
        Double payMoney = originalAmount / 100.0;
        Double discountsPrice = productTotalPrice - payMoney;

        JSONObject sku = certificate.getJSONObject("sku");
        String skuId = sku.getStr("sku_id");

        Store store = storeService.getById(order.getStoreId());

        Product product = productService.getOne(PRODUCT.DOUYIN_PRODUCT_ID.eq(skuId));
        Assert.notNull(product, () -> new CodeException("券码对应产品未在斑得清系统初始化"));
        ProductSpecification ps = productSpecificationService.getOne(PRODUCT_SPECIFICATION.PRODUCT_ID.eq(product.getProductId()));
        Assert.notNull(ps, () -> new CodeException("抖音团购请配置一个基础套餐即可"));
        ProductInventory pi = productInventoryService.getOne(QueryWrapper.create()
                .where(PRODUCT_INVENTORY.PRODUCT_ID.eq(product.getProductId()))
                .where(PRODUCT_INVENTORY.PRODUCT_SPECIFICATION_ID.eq(ps.getProductSpecificationId()))
                .where(PRODUCT_INVENTORY.STORE_ID.eq(store.getStoreId())));
        Assert.notNull(pi, () -> new CodeException("店铺未入库抖音团购产品"));

        String verifyToken = data.getStr("verify_token");
        String encryptedCode = certificate.getStr("encrypted_code");
        String orderId = data.getStr("order_id");

        JSONObject entries = DouYinUtil.certificateVerify(verifyToken, store.getDouyinPoiId(), encryptedCode, orderId);
        JSONObject jsonObject = entries.getJSONObject("data");
        Integer errorCode = jsonObject.getInt("error_code", -1);
        if (errorCode != 0) {
            String description = jsonObject.getStr("description");
            return Resp.error(description);
        }

        Double payDeposit = ObjUtil.defaultIfNull(order.getPayDeposit(), 0.0);
        Double payFinalPayment = ObjUtil.defaultIfNull(order.getPayFinalPayment(), 0.0);
        Double orderProductTotalPrice = ObjUtil.defaultIfNull(order.getProductTotalPrice(), 0.0) + productTotalPrice;

        Double oldTotalPrice = ObjUtil.defaultIfNull(order.getTotalPrice(), 0.0);
        Double totalPrice = oldTotalPrice + payMoney;
        Double updateDiscountsPrice = ObjUtil.defaultIfNull(order.getDiscountsPrice(), 0.0) + discountsPrice;

//        OrderStatus orderStatus = OrderStatus.confirm.equals(order.getOrderStatus()) ? null : OrderStatus.confirm;

        PayRecord pr = converter.convert(req, PayRecord.class);
        pr.setPaySource(PaySource.douyin);
        pr.setDouyinCodeStatus(DouyinCodeStatus.pass);

        if (PayType.prepay.equals(pr.getPayType())) {
            payDeposit += payMoney;
        } else if (PayType.final_payment.equals(pr.getPayType())) {
            payFinalPayment += payMoney;
        }

        Order updateOrder = Order.builder()
                .orderId(order.getOrderId())
//                .orderStatus(orderStatus)
                .payDeposit(payDeposit)
                .payFinalPayment(payFinalPayment)
                .discountsPrice(updateDiscountsPrice)
                .totalPrice(totalPrice)
                .productTotalPrice(orderProductTotalPrice)
                .build();

        if (PayType.prepay.equals(pr.getPayType()) && !order.getOrderStatus().equals(OrderStatus.confirm)) {
            updateOrder.setOrderStatus(OrderStatus.confirm);
        } else if (PayType.final_payment.equals(pr.getPayType()) && !order.getOrderStatus().equals(OrderStatus.complete)) {
            updateOrder.setOrderStatus(OrderStatus.complete);
        }

        if (ObjUtil.isNull(order.getProductId())) {
            updateOrder.setProductId(product.getProductId());
            updateOrder.setProductName(product.getProductName());
        }

        Assert.isTrue(orderService.updateById(updateOrder), CodeException::new);

        OrderDiscounts od = OrderDiscounts.builder()
                .orderId(order.getOrderId())
                .beforeTotalPrice(oldTotalPrice + orderProductTotalPrice)
                .discountsMoney(discountsPrice)
                .afterTotalPrice(totalPrice)
                .discountsType(DiscountsType.douyin)
                .discountsRemark("抖音团购" + product.getProductName() + "优惠" + discountsPrice + "元")
                .build();
        Assert.isTrue(orderDiscountsService.save(od), CodeException::new);

        pr.setPayMoney(payMoney);
        pr.setPayBeforeDeposit(order.getPayDeposit());
        pr.setPayAfterDeposit(payDeposit);
        pr.setPayBeforeFinalPayment(order.getPayFinalPayment());
        pr.setPayAfterFinalPayment(payFinalPayment);
        pr.setPayBeforeTotalPrice(order.getTotalPrice());
        pr.setPayAfterTotalPrice(totalPrice);
        Assert.isTrue(payRecordService.save(pr), CodeException::new);

        Integer before = pi.getProductInventory();
        Integer after = pi.getProductInventory() - 1;
        ProductInventory updatePi = ProductInventory.builder()
                .inventoryId(pi.getInventoryId())
                .productInventory(after)
                .build();
        Assert.isTrue(productInventoryService.updateById(updatePi), CodeException::new);

        ProductInventoryRecord pir = ProductInventoryRecord.builder()
                .inventoryId(pi.getInventoryId())
                .productId(pi.getProductId())
                .productSpecificationId(ps.getProductSpecificationId())
                .productSpecification(ps.getProductSpecification())
                .productId(product.getProductId())
                .productName(product.getProductName())
                .productPrice(productTotalPrice)
                .productTotalPrice(productTotalPrice)
                .storeId(store.getStoreId())
                .storeName(store.getStoreName())
                .beforeInventory(before)
                .changeInventory(1)
                .afterInventory(after)
                .orderId(order.getOrderId())
                .changeType(ChangeType.order_save)
                .remark("订单抖音验券订单新增")
                .build();
        Assert.isTrue(productInventoryRecordService.save(pir), CodeException::new);
        return Resp.success();
    }

    @Override
    public synchronized Resp<Void> cancelDouyin(CancelDouyinReq req) {
        PayRecord pr = payRecordService.getById(req.getPayId());
        Assert.isTrue(DouyinCodeStatus.pass.equals(pr.getDouyinCodeStatus()), () -> new CodeException("抖音券状态不是已核验"));

        return Resp.success();
    }

//    @Override
//    public void create(OrderCreateReq req) {
//        Order order = converter.convert(req, Order.class);
//        Assert.isTrue(orderService.save(order), () -> new CodeException("orderService.save(order)"));
//        return Resp.success();
//    }

}
